/*根据IMX6ULL芯片手册<<34.6 elcdif Memory Map/Register Definition>>2165页，定义elcdif的结构体,*/
struct imx6ull_lcdif {
  volatile unsigned int CTRL;                              
  volatile unsigned int CTRL_SET;                        
  volatile unsigned int CTRL_CLR;                         
  volatile unsigned int CTRL_TOG;                         
  volatile unsigned int CTRL1;                             
  volatile unsigned int CTRL1_SET;                         
  volatile unsigned int CTRL1_CLR;                       
  volatile unsigned int CTRL1_TOG;                       
  volatile unsigned int CTRL2;                            
  volatile unsigned int CTRL2_SET;                       
  volatile unsigned int CTRL2_CLR;                        
  volatile unsigned int CTRL2_TOG;                        
  volatile unsigned int TRANSFER_COUNT;   
       unsigned char RESERVED_0[12];
  volatile unsigned int CUR_BUF;                          
       unsigned char RESERVED_1[12];
  volatile unsigned int NEXT_BUF;                        
       unsigned char RESERVED_2[12];
  volatile unsigned int TIMING;                          
       unsigned char RESERVED_3[12];
  volatile unsigned int VDCTRL0;                         
  volatile unsigned int VDCTRL0_SET;                      
  volatile unsigned int VDCTRL0_CLR;                     
  volatile unsigned int VDCTRL0_TOG;                     
  volatile unsigned int VDCTRL1;                          
       unsigned char RESERVED_4[12];
  volatile unsigned int VDCTRL2;                          
       unsigned char RESERVED_5[12];
  volatile unsigned int VDCTRL3;                          
       unsigned char RESERVED_6[12];
  volatile unsigned int VDCTRL4;                           
       unsigned char RESERVED_7[12];
  volatile unsigned int DVICTRL0;    
  	   unsigned char RESERVED_8[12];
  volatile unsigned int DVICTRL1;                         
       unsigned char RESERVED_9[12];
  volatile unsigned int DVICTRL2;                        
       unsigned char RESERVED_10[12];
  volatile unsigned int DVICTRL3;                        
       unsigned char RESERVED_11[12];
  volatile unsigned int DVICTRL4;                          
       unsigned char RESERVED_12[12];
  volatile unsigned int CSC_COEFF0;  
  	   unsigned char RESERVED_13[12];
  volatile unsigned int CSC_COEFF1;                        
       unsigned char RESERVED_14[12];
  volatile unsigned int CSC_COEFF2;                        
       unsigned char RESERVED_15[12];
  volatile unsigned int CSC_COEFF3;                        
       unsigned char RESERVED_16[12];
  volatile unsigned int CSC_COEFF4;   
  	   unsigned char RESERVED_17[12];
  volatile unsigned int CSC_OFFSET;  
       unsigned char RESERVED_18[12];
  volatile unsigned int CSC_LIMIT;  
       unsigned char RESERVED_19[12];
  volatile unsigned int DATA;                              
       unsigned char RESERVED_20[12];
  volatile unsigned int BM_ERROR_STAT;                     
       unsigned char RESERVED_21[12];
  volatile unsigned int CRC_STAT;                        
       unsigned char RESERVED_22[12];
  volatile  unsigned int STAT;                             
       unsigned char RESERVED_23[76];
  volatile unsigned int THRES;                             
       unsigned char RESERVED_24[12];
  volatile unsigned int AS_CTRL;                           
       unsigned char RESERVED_25[12];
  volatile unsigned int AS_BUF;                            
       unsigned char RESERVED_26[12];
  volatile unsigned int AS_NEXT_BUF;                     
       unsigned char RESERVED_27[12];
  volatile unsigned int AS_CLRKEYLOW;                    
       unsigned char RESERVED_28[12];
  volatile unsigned int AS_CLRKEYHIGH;                   
       unsigned char RESERVED_29[12];
  volatile unsigned int SYNC_DELAY;                      
} lcdif_Type;

int lcd_controller_init(struct imx6ull_lcdif *lcdif, struct display_timing *dt, int lcd_bpp,int fb_bpp, unsigned int fb_phy)
{
	int lcd_data_bus_width;
	int fb_width;
	int vsync_pol = 0;	
	int hsync_pol = 0;
	int de_pol = 0;  /*决定是否接受RGB数据，在像素点跳转时禁用RGB数据*/
	int clk_pol = 0;
	
	if(dt->flags & DISPLAY_FLAGS_HSYNC_HIGH)
		hsync_pol = 1;
	if(dt->flags & DISPLAY_FLAGS_VSYNC_HIGH)
		vsync_pol = 1;
	if(dt->flags & DISPLAY_FLAGS_DE_HIGH)
		de_pol = 1;
	if(dt->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
		clk_pol = 1;
	
	if(lcd_bpp == 24 || lcd_bpp == 32)
		lcd_data_bus_width = 0x3;
	else if(lcd_bpp == 18)
		lcd_data_bus_width = 0x2; 	
	else if(lcd_bpp == 8)
		lcd_data_bus_width = 0x1; 	
	else if(lcd_bpp == 16)
		lcd_data_bus_width = 0x0; 
	else 
		return -1;
	
	if(fb_bpp == 24)
		fb_width = 0x3;
	else if(fb_bpp == 18)
		fb_width = 0x2; 	
	else if(fb_bpp == 8)
		fb_width = 0x1; 	
	else if(fb_bpp == 16)
		fb_width = 0x0; 
	else 
		return -1;
	
	lcdif->CTRL = (0 << 30) | (0 << 29) | (0 << 28) | (1 << 19) | (1 << 17) | (lcd_data_bus_width << 10) |\
				  (fb_width << 8) | (1 << 5);

   /*
	* 设置Elcdif的寄存器CTRL1
	* 根据bpp设置，bpp为24或32才设置
	* [19:16]  : 111  :表示ARGB传输格式模式下，传输24位无压缩数据，A通道不用传输）
	*/	  
   if(fb_bpp == 24 || fb_bpp == 32)
   {	  
		  lcdif->CTRL1 &= ~(0xf << 16); 
		  lcdif->CTRL1 |=  (0x7 << 16); 
   }else 
		lcdif->CTRL1 |=	(0xf << 16); 
	  
	/*
	* 设置Elcdif的寄存器TRANSFER_COUNT寄存器
	* [31:16]  : 垂直方向上的像素个数  
	* [15:0]   : 水平方向上的像素个数
	*/
  lcdif->TRANSFER_COUNT  = (dt->vactive.typ << 16) | (dt->hactive.typ << 0);
  
  /*
   * 设置Elcdif的VDCTRL0寄存器
   * [29] 0 : VSYNC输出  ，默认为0，无需设置
   * [28] 1 : 在DOTCLK模式下，设置1硬件会产生使能ENABLE输出
   * [27] 0 : VSYNC低电平有效	,根据屏幕配置文件将其设置为0
   * [26] 0 : HSYNC低电平有效 , 根据屏幕配置文件将其设置为0
   * [25] 1 : DOTCLK下降沿有效 ，根据屏幕配置文件将其设置为1
   * [24] 1 : ENABLE信号高电平有效，根据屏幕配置文件将其设置为1
   * [21] 1 : 帧同步周期单位，DOTCLK mode设置为1
   * [20] 1 : 帧同步脉冲宽度单位，DOTCLK mode设置为1
   * [17:0] :  vysnc脉冲宽度 
   */
	  lcdif->VDCTRL0 = (1 << 28)|( vsync_pol << 27)\
					  |( hsync_pol << 26)\
					  |( clk_pol << 25)\
					  |(de_pol << 24)\
					  |(1 << 21)|(1 << 20)|( dt->vsync_len.typ << 0);
  
  /*
   * 设置Elcdif的VDCTRL1寄存器
   * 设置垂直方向的总周期:上黑框tvb+垂直同步脉冲tvp+垂直有效高度yres+下黑框tvf
   */	  
	lcdif->VDCTRL1 = dt->vback_porch.typ + dt->vsync_len.typ + dt->vactive.typ + dt->vfront_porch.typ;  
  
  /*
   * 设置Elcdif的VDCTRL2寄存器
   * [18:31]  : 水平同步信号脉冲宽度
   * [17: 0]   : 水平方向总周期
   * 设置水平方向的总周期:左黑框thb+水平同步脉冲thp+水平有效高度xres+右黑框thf
   */ 
  
   lcdif->VDCTRL2 = (dt->hsync_len.typ << 18) | (dt->hback_porch.typ + dt->hsync_len.typ + dt->hactive.typ + dt->hfront_porch.typ);
  
   /*
	* 设置Elcdif的VDCTRL3寄存器
	* [27:16] ：水平方向上的等待时钟数 =thb + thp
	* [15:0]  : 垂直方向上的等待时钟数 = tvb + tvp
	*/ 
	
   lcdif->VDCTRL3 = ((dt->hback_porch.typ + dt->hsync_len.typ) << 16) | (dt->vback_porch.typ + dt->vsync_len.typ);
  
   /*
	* 设置Elcdif的VDCTRL4寄存器
	* [18]	   使用VSHYNC、HSYNC、DOTCLK模式此为置1
	* [17:0]  : 水平方向的宽度
	*/ 
  
   lcdif->VDCTRL4 = (1<<18) | (dt->hactive.typ);
  
   /*
	* 设置Elcdif的CUR_BUF和NEXT_BUF寄存器
	* CUR_BUF	 :	当前显存地址
	* NEXT_BUF :	下一帧显存地址
	* 方便运算，都设置为同一个显存地址
	*/ 
	
  lcdif->CUR_BUF  =  fb_phy;
  lcdif->NEXT_BUF =  fb_phy;
					  
	
}

